package com.jackeysun.common

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import java.lang.NullPointerException

open class AbsAdapter<T : IData> :
    RecyclerView.Adapter<RecyclerView.ViewHolder> {
    constructor()

    constructor(block: (adapter: AbsAdapter<T>, view: View, position: Int) -> Unit) {
        this.block = block
    }

    constructor(
        layoutId: Int = -1,
        block: (adapter: AbsAdapter<T>, view: View, position: Int) -> Unit,
    ) {
//        this.layoutId = layoutId
        this.block = block
        if (layoutId != -1) {
            layoutIds[0] = layoutId
        }
    }

    private var block: (adapter: AbsAdapter<T>, view: View, position: Int) -> Unit =
        { adapter: AbsAdapter<T>, view: View, position: Int -> }

    lateinit var data: MutableList<T>
    private val layoutIds by lazy { mutableMapOf<Int, Int>() }
    private val viewIds by lazy { mutableListOf<Int>() }


    open fun addLayout(type: Int, @LayoutRes layoutResId: Int) {
        layoutIds[type] = layoutResId
    }

    open fun addClickId(@IdRes id: Int) {
        viewIds.add(id)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return createHolder(parent, viewType)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        data[position].bind(holder)
        viewIds.distinct().map { id ->
            val view: View? = holder.itemView `$` id
            view?.setOnClickListener { block(this, it, position) }
        }
    }

    override fun getItemCount(): Int = try {
        data.size
    } catch (e: Exception) {
        0
    }

    override fun getItemViewType(position: Int): Int = data[position].getType()

    fun getItem(position: Int): T = data[position]

    private fun createHolder(parent: ViewGroup, viewType: Int): AbsViewHolder {
        val rootView =
            parent.getItemView(layoutIds[viewType] ?: throw NullPointerException("需要一个布局"))
        return AbsViewHolder(rootView)
    }

    private fun ViewGroup.getItemView(@LayoutRes layoutResId: Int): View {
        return LayoutInflater.from(this.context).inflate(layoutResId, this, false)
    }

    fun notifyDataChanged(
        newList: MutableList<T>,
        block: (oldItemPosition: Int, newItemPosition: Int) -> Any?,
    ) {
        val diffResult: DiffUtil.DiffResult =
            DiffUtil.calculateDiff(DiffCallback(data, newList, block))
        diffResult.dispatchUpdatesTo(this)
        data.clear()
        data = newList
    }
}

class DiffCallback<T>(
    val oldList: List<T>,
    val newList: List<T>,
    val block: (oldItemPosition: Int, newItemPosition: Int) -> Any?,
) : DiffUtil.Callback() {
    override fun getOldListSize(): Int = oldList.size

    override fun getNewListSize(): Int = newList.size

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = true

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
        oldList[oldItemPosition] == newList[newItemPosition]

    override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
        return block(oldItemPosition, newItemPosition)
    }
}